import Socket from '../../socket';

const refreshTokenQueue = [], whiteList = ['/api/auth/login', '/api/auth/token'];

export default function (context, config) {
    return new Promise((resolve, reject) => {
        const $token = context.$vue.prototype.$token,
            $jwt = context.$vue.prototype.$jwt,
            $config = context.$configure,
            $nativeAjax = context.$vue.prototype.$nativeAjax,
            expiredResponse = { response: { data: { message: '登录已过期', code: 401 } } };

        if(whiteList.includes(config.url)){
            resolve();
        }else{
            if($token.isExpired()){
                if($token.refreshTokenIsExpired()){
                    context.$vue.prototype.$closeAllMask();

                    reject(expiredResponse);
                }else{
                    refreshTokenQueue.push({ resolve, config });

                    $nativeAjax({
                        baseURL: $config.get('httpBaseUrl'),
                        url: '/api/auth/token',
                        method: 'post',
                        data: {
                            refreshToken: $token.getRefreshToken()
                        }
                    }).then(({ data: { token, refreshToken } }) => {
                        setToken(token, 'Token', `Bearer ${token}`);

                        setToken(refreshToken, 'RefreshToken', refreshToken);

                        Socket.resetConnect();

                        function setToken(tokenStr, prefix, value){
                            let { iat, exp } = $jwt.decode(tokenStr), expiration = 0;

                            if (iat && exp) {
                                let ttl = exp - iat;

                                if (ttl > 0) {
                                    expiration = new Date().valueOf() + ttl * 1000;
                                }
                            }

                            $token[`set${prefix}`](value, expiration);
                        }

                        localStorage.setItem('tb_jwt_token', token);
                        localStorage.setItem('tb_refresh_token', refreshToken);

                        refreshTokenQueue.forEach(item => item.resolve(item.config));
                    }).catch(e => {
                        context.$vue.prototype.$closeAllMask();

                        reject(expiredResponse);
                    });
                }
            }else{
                resolve();
            }
        }
    });
}
